home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1997 July
/
EnigmA AMIGA RUN 20 (1997)(G.R. Edizioni)(IT)[!][issue 1997-07 & 08][EAR-CD IV].iso
/
earcd
/
game
/
text
/
lists.lha
/
listsdir
/
zlisp-funs.inf
< prev
next >
Wrap
Text File
|
1996-12-06
|
14KB
|
644 lines
Constant MAX_LIST_ARGS 4;
Array list_args --> MAX_LIST_ARGS;
Global num_list_args;
Array aname_quote string "quote";
Array aname_internal_dict string "internal-dict";
Array aname_error string "error";
Array aname_nil string "nil";
Array aname_t string "t";
Array aname_s string "s";
Array aname_s2 string "s2";
Array aname_s3 string "s3";
Array aname_not string "not";
Array aname_eqvp string "eqv?";
Array aname_equalp string "equal?";
Array aname_nullp string "null?";
Array aname_listp string "list?";
Array aname_eqnum string "=";
Array aname_gt string ">";
Array aname_lt string "<";
Array aname_gte string ">=";
Array aname_lte string "<=";
Array aname_plus string "+";
Array aname_minus string "-";
Array aname_car string "car";
Array aname_cdr string "cdr";
Array aname_cons string "cons";
Array aname_length string "length";
Array aname_cond string "cond";
Array aname_lambda string "lambda";
Array aname_define string "define";
Array aname_let string "let";
Array aname_letstar string "let*";
Array aname_letrec string "letrec";
Array aname_list string "list";
Array aname_eval string "eval";
Global atom_quote;
Global atom_t;
Global atom_s;
Global atom_s2;
Global atom_s3;
! --- startup code
[ make_initial_stuff
dict atm ix;
dict = 0;
top_level_env = 0;
atm = string_to_atom(aname_quote);
if (atm == tok_Error)
return tok_Error;
atom_quote = atm;
dict = alloc_cons(atm, dict);
atm = string_to_atom(aname_s);
if (atm == tok_Error)
return tok_Error;
atom_s = atm;
dict = alloc_cons(atm, dict);
atm = string_to_atom(aname_s2);
if (atm == tok_Error)
return tok_Error;
atom_s2 = atm;
dict = alloc_cons(atm, dict);
atm = string_to_atom(aname_s3);
if (atm == tok_Error)
return tok_Error;
atom_s3 = atm;
dict = alloc_cons(atm, dict);
if (dict == tok_Error)
return tok_Error;
! finished with dictionary. Now add it, and other stuff, to the top_level_env.
atm = string_to_atom(aname_internal_dict);
if (atm == tok_Error)
return tok_Error;
ix = alloc_cons(atm, dict);
top_level_env = alloc_cons(ix, top_level_env);
if (top_level_env == tok_Error)
return tok_Error;
if (build_function(bt_Form, aname_error, -1, #r$fn_error) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_plus, -1, #r$fn_plus) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_minus, -1, #r$fn_minus) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_gt, -1, #r$fn_gt) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_lt, -1, #r$fn_lt) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_gte, -1, #r$fn_gte) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_lte, -1, #r$fn_lte) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_eqnum, -1, #r$fn_eqnum) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_eqvp, 2, #r$fn_eqvp) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_equalp, 2, #r$fn_equalp) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_not, 1, #r$fn_not) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_nullp, 1, #r$fn_nullp) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_listp, 1, #r$fn_listp) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_list, -1, #r$fn_list) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_length, 1, #r$fn_length) == tok_Error)
return tok_Error;
if (build_function(bt_Form, aname_cond, -1, #r$fn_cond) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_eval, 1, #r$fn_eval) == tok_Error)
return tok_Error;
if (build_function(bt_Form, aname_define, 2, #r$fn_define) == tok_Error)
return tok_Error;
if (build_function(bt_Form, aname_let, 2, #r$fn_let) == tok_Error)
return tok_Error;
if (build_function(bt_Form, aname_letrec, 2, #r$fn_letrec) == tok_Error)
return tok_Error;
if (build_function(bt_Form, aname_letstar, 2, #r$fn_letstar) == tok_Error)
return tok_Error;
if (build_function(bt_Form, aname_lambda, 2, #r$fn_lambda) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_car, 1, #r$fn_car) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_cdr, 1, #r$fn_cdr) == tok_Error)
return tok_Error;
if (build_function(bt_Function, aname_cons, 2, #r$fn_cons) == tok_Error)
return tok_Error;
if (build_function(bt_Form, aname_quote, 1, #r$fn_quote) == tok_Error)
return tok_Error;
atm = string_to_atom(aname_nil);
if (atm == tok_Error)
return tok_Error;
ix = alloc_cons(atm, 0);
top_level_env = alloc_cons(ix, top_level_env);
if (top_level_env == tok_Error)
return tok_Error;
atm = string_to_atom(aname_t);
if (atm == tok_Error)
return tok_Error;
ix = alloc_cons(atm, atm);
top_level_env = alloc_cons(ix, top_level_env);
if (top_level_env == tok_Error)
return tok_Error;
atom_t = atm;
return 0;
];
[ build_function funcform fname args fptr
atm ix val;
atm = string_to_atom(fname);
if (atm == tok_Error)
return tok_Error;
val = alloc_node(funcform, 0,
alloc_node(bt_Builtin, num_to_atom(args), num_to_atom(fptr)));
if (val == tok_Error)
return tok_Error;
ix = alloc_cons(atm, val);
ix = alloc_cons(ix, top_level_env);
if (ix == tok_Error)
return tok_Error;
top_level_env = ix;
return 0;
];
! --- the built-in functions and forms. Note that the supplied arguments
! will never be tok_Error, and there will be the right number of them.
[ fn_debug
ix;
print "[debug got ", num_list_args, " args:^";
for (ix=0 : ix < num_list_args : ix++) {
print " ", ix, ": ";
write_obj(list_args-->ix);
new_line;
}
print "]^";
return 0;
];
[ fn_quote;
return list_args-->0;
];
[ fn_list;
return list_args-->0;
];
[ fn_lambda env
v;
v = list_args-->0;
if (v ~= 0 && v->0 ~= bt_Cons && v->0 ~= bt_Atom) {
show_error("lambda: bad argument template", v, 1);
return tok_Error;
}
v = alloc_node(bt_Dynamic, v, list_args-->1);
if (v == tok_Error)
return tok_Error;
v = alloc_node(bt_Function, env, v);
if (v == tok_Error)
return tok_Error;
return v;
];
[ fn_define env
envp namat def s;
namat = list_args-->0;
def = list_args-->1;
if (namat == 0 || namat->0 ~= bt_Atom) {
show_error("define: first argument is not an atom", namat, 1);
return tok_Error;
}
def = eval_obj(def, env);
if (def == tok_Error)
return tok_Error;
envp = top_level_env;
for ( : envp ~= 0 : envp = envp-->2) {
s = envp-->1;
if ((s-->1)-->1 == namat-->1) {
break;
}
}
if (envp == 0) {
! didn't find the atom; add it to top_level_env
s = alloc_cons(namat, def);
s = alloc_cons(s, top_level_env);
if (s == tok_Error)
return tok_Error;
top_level_env = s;
}
else {
! found it; it's s.
s-->2 = def;
}
return def;
];
[ fn_eval env
s;
s = list_args-->0;
s = eval_obj(s, env);
return s;
];
[ fn_let env
defs expr s atm adef newenv;
defs = list_args-->0;
expr = list_args-->1;
if (defs ~= 0 && defs->0 ~= bt_Cons) {
show_error("let: first argument is not a list of lists", defs, 1);
return tok_Error;
}
newenv = env;
for ( : defs~=0 : defs=defs-->2 ) {
s = defs-->1;
if (s ~= 0 && s->0 ~= bt_Cons) {
show_error("let: binding is not a list", s, 1);
return tok_Error;
}
atm = s-->1;
if (atm == 0 || atm->0 ~= bt_Atom) {
show_error("let: binding must start with an atom", s, 1);
return tok_Error;
}
adef = s-->2;
if (adef == 0 || adef->0 ~= bt_Cons) {
show_error("let: binding must contain a definition", s, 1);
return tok_Error;
}
adef = adef-->1;
adef = eval_obj(adef, env);
if (adef == tok_Error)
return tok_Error;
newenv = alloc_cons(alloc_cons(atm, adef), newenv);
if (newenv == tok_Error)
return tok_Error;
}
s = eval_obj(expr, newenv);
return s;
];
[ fn_letrec env
origdefs defs expr s atm adef newenv tmpenv;
origdefs = list_args-->0;
expr = list_args-->1;
if (origdefs ~= 0 && origdefs->0 ~= bt_Cons) {
show_error("letrec: first argument is not a list of lists", origdefs, 1);
return tok_Error;
}
newenv = env;
for ( defs = origdefs : defs~=0 : defs=defs-->2 ) {
s = defs-->1;
if (s ~= 0 && s->0 ~= bt_Cons) {
show_error("letrec: binding is not a list", s, 1);
return tok_Error;
}
atm = s-->1;
if (atm == 0 || atm->0 ~= bt_Atom) {
show_error("letrec: binding must start with an atom", s, 1);
return tok_Error;
}
adef = 0;
newenv = alloc_cons(alloc_cons(atm, adef), newenv);
if (newenv == tok_Error)
return tok_Error;
}
tmpenv = newenv;
for ( defs = origdefs : defs~=0 : defs=defs-->2 ) {
s = defs-->1;
atm = s-->1;
adef = s-->2;
if (adef == 0 || adef->0 ~= bt_Cons) {
show_error("letrec: binding must contain a definition", s, 1);
return tok_Error;
}
adef = adef-->1;
adef = eval_obj(adef, newenv);
if (adef == tok_Error)
return tok_Error;
(tmpenv-->1)-->1 = atm;
(tmpenv-->1)-->2 = adef;
tmpenv = tmpenv-->2;
}
s = eval_obj(expr, newenv);
return s;
];
[ fn_letstar env
defs expr s atm adef;
defs = list_args-->0;
expr = list_args-->1;
if (defs ~= 0 && defs->0 ~= bt_Cons) {
show_error("let: first argument is not a list of lists", defs, 1);
return tok_Error;
}
for ( : defs~=0 : defs=defs-->2 ) {
s = defs-->1;
if (s ~= 0 && s->0 ~= bt_Cons) {
show_error("let: binding is not a list", s, 1);
return tok_Error;
}
atm = s-->1;
if (atm == 0 || atm->0 ~= bt_Atom) {
show_error("let: binding must start with an atom", s, 1);
return tok_Error;
}
adef = s-->2;
if (adef == 0 || adef->0 ~= bt_Cons) {
show_error("let: binding must contain a definition", s, 1);
return tok_Error;
}
adef = adef-->1;
adef = eval_obj(adef, env);
if (adef == tok_Error)
return tok_Error;
env = alloc_cons(alloc_cons(atm, adef), env);
if (env == tok_Error)
return tok_Error;
}
s = eval_obj(expr, env);
return s;
];
[ fn_length
s len;
len = 0;
for (s = list_args-->0 : s ~= 0 : s = s-->2, len++ ) {
if (s->0 ~= bt_Cons) {
show_error("length: not a proper list", list_args-->0, 1);
return tok_Error;
}
}
return num_to_atom(len);
];
[ fn_cons;
return alloc_cons(list_args-->0, list_args-->1);
];
[ fn_car
s;
s = list_args-->0;
if (s == 0 || s->0 ~= bt_Cons) {
show_error("car: bad argument", s, 1);
return tok_Error;
}
return (s-->1);
];
[ fn_cdr
s;
s = list_args-->0;
if (s == 0 || s->0 ~= bt_Cons) {
show_error("cdr: bad argument", s, 1);
return tok_Error;
}
return (s-->2);
];
[ fn_not
;
if (is_true(list_args-->0) ~= 0)
return 0;
else
return atom_t;
];
[ fn_nullp
;
if (list_args-->0 ~= 0)
return 0;
else
return atom_t;
];
[ fn_listp
s;
s = list_args-->0;
if (s == 0)
return atom_t;
if (s->0 == bt_Cons)
return atom_t;
return 0;
];
[ fn_cond env
s cl tex cle;
s = list_args-->0;
for ( : s ~= 0 : s = s-->2) {
if (s->0 ~= bt_Cons) {
show_error("cond: argument is not a list", s, 1);
return tok_Error;
}
cl = s-->1;
if (cl->0 ~= bt_Cons) {
show_error("cond: clause is not a list", cl, 1);
return tok_Error;
}
tex = cl-->1;
tex = eval_obj(tex, env);
if (tex == tok_Error)
return tok_Error;
if (is_true(tex) ~= 0) {
cle = cl-->2;
if (cle == 0)
return tex;
if (cle->0 ~= bt_Cons) {
show_error("cond: clause does not end in an expression", cl, 1);
return tok_Error;
}
tex = eval_obj(cle-->1, env);
return tex;
}
}
return 0;
];
[ fn_eqvp
s1 s2;
s1 = list_args-->0;
s2 = list_args-->1;
if (s1 == s2)
return atom_t;
if (s1 == 0 || s2 == 0)
return 0;
if (s1->0 ~= s2->0)
return 0;
switch (s1->0) {
bt_Atom, bt_Num:
if (s1-->1 == s2-->1)
return atom_t;
return 0;
bt_Cons:
return 0;
default:
return 0;
}
];
[ fn_equalp
;
return is_equalp(list_args-->0, list_args-->1);
];
[ is_equalp s1 s2;
if (s1 == s2)
return atom_t;
if (s1 == 0 || s2 == 0)
return 0;
if (s1->0 ~= s2->0)
return 0;
switch (s1->0) {
bt_Atom, bt_Num:
if (s1-->1 == s2-->1)
return atom_t;
return 0;
bt_Cons:
if (is_equalp(s1-->1, s2-->1) == 0)
return 0;
if (is_equalp(s1-->2, s2-->2) == 0)
return 0;
return atom_t;
default:
return 0;
}
];
[ fn_gt;
return fn_numcompare(aname_gt);
];
[ fn_lt;
return fn_numcompare(aname_lt);
];
[ fn_gte;
return fn_numcompare(aname_gte);
];
[ fn_lte;
return fn_numcompare(aname_lte);
];
[ fn_eqnum;
return fn_numcompare(aname_eqnum);
];
[ fn_numcompare op
s v cur;
s = list_args-->0;
if (s == 0) {
show_error("numeric compare: must have at least one argument");
return tok_Error;
}
v = s-->1;
if (v == 0 || v->0 ~= bt_Num) {
show_error("numeric compare: non-numeric argument", v, 1);
return tok_Error;
}
cur = v-->1;
for ( s = s-->2 : s ~= 0 : s = s-->2 ) {
v = s-->1;
if (v == 0 || v->0 ~= bt_Num) {
show_error("numeric compare: non-numeric argument", v, 1);
return tok_Error;
}
switch (op) {
aname_gt:
if (cur <= v-->1) return 0;
aname_lt:
if (cur >= v-->1) return 0;
aname_gte:
if (cur < v-->1) return 0;
aname_lte:
if (cur > v-->1) return 0;
aname_eqnum:
if (cur ~= v-->1) return 0;
}
cur = v-->1;
}
return atom_t;
];
[ fn_plus
sum ptr v;
sum = 0;
for ( ptr = list_args-->0 : ptr~=0 : ptr=ptr-->2 ) {
v = ptr-->1;
if (v == 0 || v->0 ~= bt_Num) {
show_error("+: non-numeric argument", v, 1);
return tok_Error;
}
sum = sum + v-->1;
}
return num_to_atom(sum);
];
[ fn_minus
sum ptr v pos;
sum = 0;
pos = 0;
for ( ptr = list_args-->0 : ptr~=0 : ptr=ptr-->2, pos++ ) {
v = ptr-->1;
if (v == 0 || v->0 ~= bt_Num) {
show_error("+: non-numeric argument", v, 1);
return tok_Error;
}
if (pos == 0) {
sum = sum + v-->1;
}
else {
sum = sum - v-->1;
}
}
if (pos == 1)
sum = 0-sum;
return num_to_atom(sum);
];
[ fn_error;
show_error();
return tok_Error;
];